<?php
/**
 * 极验封装
 * @author yupoxiong<i@yupoxiong.com>
 */

declare (strict_types=1);

namespace util\gt;

use JsonException;

class GeeTest
{
    protected string $gtCheckSessionKey = 'admin_login_gt_check';

    public function setGtSession($value): void
    {
        session([$this->gtCheckSessionKey => $value]);
    }

    public function getGtSession()
    {
        return session($this->gtCheckSessionKey);
    }

    public function check($param): array
    {
        $config      = setting('admin.login');
        $captcha_key = $config['gt_captcha_key'];
        $api_server  = "https://gcaptcha4.geetest.com";

        // 2.获取用户验证后前端传过来的验证流水号参数
        $captcha_id     = $param['captcha_id'];
        $lot_number     = $param['lot_number'];
        $captcha_output = $param['captcha_output'];
        $pass_token     = $param['pass_token'];
        $gen_time       = $param['gen_time'];


        // 3.生成签名
        // 生成签名使用标准的hmac算法，使用用户当前完成验证的流水号lot_number作为原始消息message，使用客户验证私钥作为key
        // 采用sha256散列算法将message和key进行单向散列生成最终的签名
        $sign_token = hash_hmac('sha256', $lot_number, $captcha_key);

        // 4.上传校验参数到极验二次验证接口, 校验用户验证状态
        // captcha_id 参数建议放在 url 后面, 方便请求异常时可以在日志中根据id快速定位到异常请求
        $query = array(
            'lot_number'     => $lot_number,
            'captcha_output' => $captcha_output,
            'pass_token'     => $pass_token,
            'gen_time'       => $gen_time,
            'sign_token'     => $sign_token
        );
        $url   = $api_server . '/validate?captcha_id=' . $captcha_id;
        return $this->postRequest($url, $query);
    }


    /**
     * @param $url
     * @param $post_data
     * 注意处理接口异常情况，当请求极验二次验证接口异常时做出相应异常处理
     *  保证不会因为接口请求超时或服务未响应而阻碍业务流程
     * @return array
     */
    public function postRequest($url, $post_data): array
    {
        $data = http_build_query($post_data);

        $options = array(
            'http' => array(
                'method'  => 'POST',
                'header'  => 'Content-type: application/x-www-form-urlencoded',
                'content' => $data,
                'timeout' => 5
            )
        );
        $context = stream_context_create($options);
        $result  = (string)file_get_contents($url, false, $context);
        try {
            return json_decode($result, true, 512, JSON_THROW_ON_ERROR);
        } catch (JsonException $e) {
            return [];
        }
    }
}